package com.lagou.rpc.consumer.client;

import com.alibaba.fastjson.JSON;
import com.lagou.rpc.common.RpcRequest;
import com.lagou.rpc.common.RpcResponse;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
@ConfigurationProperties(prefix = "myserver")
public class ServerProxy {
    //服务列表
    private List<String> host ;

    //服务耗时
    private Map<String,Long> serverTimes = new HashMap<>();
    private int hostIndex=0;
    @PostConstruct
    public void LoadHost(){
        try {

            CuratorFramework curatorClient = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(1000, 3));
        curatorClient.start();

           //获取生产者地址列表
            host = curatorClient.getChildren().forPath("/server");
            //监听子节点变更
            TreeCache cache = new TreeCache(curatorClient,"/server");
            cache.getListenable().addListener(new TreeCacheListener() {
                @Override
                public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                    ChildData childData = treeCacheEvent.getData();
                    byte[] data = childData.getData();
                    String strData = new String(data,"UTF-8");
                    String[] hostData = strData.split(" ");
                    host = Arrays.asList(hostData);

                }
            });
            //启动监听
            cache.start();

            //启动定时线城
            Executors.newScheduledThreadPool(1).scheduleAtFixedRate(()->{
                Set<Map.Entry<String, Long>> entries = serverTimes.entrySet();
                for (Map.Entry<String, Long> entry : entries) {
                    String key = entry.getKey();
                    Long value = entry.getValue();
                   long second= (value/1000)%60;
                       try {
                           if(second>5) {
                               curatorClient.delete().forPath("/server/" + key);
                               serverTimes.remove(key);
                           }else {
                               String str = key+"_"+ String.valueOf(second);
                               curatorClient.setData().forPath("/server/" + key,str.getBytes());
                               serverTimes.remove(key);
                           }

                       } catch (Exception exception) {
                           exception.printStackTrace();
                       }


                }

            },5,5, TimeUnit.SECONDS);

        } catch (Exception exception) {
            exception.printStackTrace();
        }

    }



    @Pointcut("execution(public * com.lagou.rpc.pojo.User..*.*(..))")
    public void point() { }
    @Around("point()")
    public Object loadBalancing(JoinPoint joinPoint) throws Exception {
        Object[] args = joinPoint.getArgs();
        String classzz = joinPoint.getTarget().getClass().getName();
        MethodSignature method = (MethodSignature)joinPoint.getSignature() ;
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setRequestId(UUID.randomUUID().toString());
        rpcRequest.setClassName(classzz);
        rpcRequest.setMethodName(method.getName());
        rpcRequest.setParameters(args);
        rpcRequest.setParameterTypes(method.getParameterTypes());
        String  host= geHost();
        RpcClient client = new RpcClient(host);
        Long startTime = System.currentTimeMillis();
        Object send = client.send(JSON.toJSONString(rpcRequest));
        RpcResponse rpcResponse = JSON.parseObject(send.toString(), RpcResponse.class);
        if(rpcResponse.getError()!= null){
            throw  new Exception(rpcResponse.getError());
        }
        Object result = rpcResponse.getResult();
        Long endTime = System.currentTimeMillis();
        serverTimes.put(host,startTime - endTime);
        return  JSON.parseObject(result.toString(), method.getReturnType());

    }

    /**
     * 轮询IP地址
     * @return
     */
    private String geHost() {
        long time = 5 ;
        String retHost = "";
        for (String ignored : host) {
            String[] server = ignored.split("_");
            String t = server[1];
            Long l = Long.parseLong(t);
            if(l<time){
                retHost = server[0];
            }
        }
        return  retHost;
    }


}
